//-----------------------------------------------------------------------
// <copyright file="UnorderedExpectations.cs" company="NMock2">
//
//   http://www.sourceforge.net/projects/NMock2
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using System.Linq;

namespace NMock2.Internal
{
    using System;
    using Monitoring;

    public class UnorderedExpectations : ExpectationOrderingBase, IExpectationOrdering
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="UnorderedExpectations"/> class.
        /// </summary>
        public UnorderedExpectations()
        {
            depth = 0;
            prompt = "Expected:";
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UnorderedExpectations"/> class.
        /// </summary>
        /// <param name="depth">The calling depth.</param>
        public UnorderedExpectations(int depth)
        {
            this.depth = depth;
            prompt = "Unordered:";
        }

        /// <summary>
        /// Gets a value indicating whether this instance is active.
        /// </summary>
        /// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
        public bool IsActive
        {
            get
            {
            	return expectations.Any(e => e.IsActive);
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance has been met.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance has been met; otherwise, <c>false</c>.
        /// </value>
        public bool HasBeenMet
        {
            get
            {
            	return expectations.All(e => e.HasBeenMet);
            }
        }

        /// <summary>
        /// Checks whether stored expectations matches the specified invocation.
        /// </summary>
        /// <param name="invocation">The invocation to check.</param>
        /// <returns>Returns whether one of the stored expectations has met the specified invocation.</returns>
        public bool Matches(Invocation invocation)
        {
        	return expectations.Any(e => e.Matches(invocation));
        }

    	public bool MatchesIgnoringIsActive(Invocation invocation)
    	{
    		return expectations.Any(e => e.MatchesIgnoringIsActive(invocation));
    	}

    	/// <summary>
        /// Performs the specified invocation on the corresponding expectation if a match was found.
        /// </summary>
        /// <param name="invocation">The invocation to match.</param>
        public void Perform(Invocation invocation)
        {
            foreach (IExpectation e in expectations)
            {
                if (e.Matches(invocation))
                {
                    e.Perform(invocation);
                    return;
                }
            }

            throw new InvalidOperationException("No matching expectation");
        }

    	public bool IsOrdered
    	{
    		get
    		{
    			return false;
    		}
    	}

		public bool ContainsOrderedExpectationFor(Invocation invocation)
		{
			foreach (IExpectation expectation in expectations)
			{
				if (expectation as IExpectationOrdering != null)
				{
					return ((IExpectationOrdering)expectation).ContainsOrderedExpectationFor(invocation);
				}
				else if (expectation.Matches(invocation))
				{
					return false;
				}
			}
			return false;
		}
    }
}
